Cloud API

(0 reviews)

Asynchronous results & notifications

A card transaction takes real-world time: the customer has to present a card, possibly enter a

PIN, and the issuer has to authorise. The Cloud API therefore supports two ways of returning a

result — synchronously in the HTTP response, or asynchronously through a notification sent

to a URL you provide.

Understanding this is essential: an HTTP 202 is not an error, and a transaction that returns

202 is very likely to succeed.

How it works

You control the behaviour with the waitTime query parameter (1–300 seconds, default 20) on

process-transaction and cancel-transaction.

  1. You call POST /process-transaction/{terminal-id}?waitTime=20, includingecrParams.notificationUrl in the body.
  2. The terminal starts the transaction. As it progresses, the API POSTs **progressnotifications** to your notificationUrl.
  3. Then one of two things happens:
OutcomeHTTP responseWhere the result arrives
The terminal finishes within waitTime201 (or 200 for cancel-transaction) with the full result in the bodyIn the HTTP response
The terminal takes longer than waitTime202 Accepted, no result bodyLater, as a notification POSTed to your notificationUrl

Warning
HTTP 202 is not a failure. It means "accepted, still in progress". Do not roll back, retry,
or show an error to the cashier. Wait for the notification, or recover with
GET /last-transaction/{terminal-id}.

Progress notifications are sent in both cases — they are not exclusive to the 202 path.

Setting up your notification endpoint

Provide the URL in every transaction request, inside ecrParams:

{
  "transactionType": "PURCHASE",
  "amount": "1000",
  "currency": "978",
  "ecrTransactionId": "ECR-mrt1levt-eqi21j",
  "ecrParams": {
    "ecrId": "POS_01",
    "notificationUrl": "https://pos.example.com/webhook/notify/9f2a77c1"
  }
}

Requirements for the endpoint:

  • It must be publicly reachable over HTTPS. The API calls it from the internet, so alocalhost address will never work. For local development, expose your machine with a tunnel(for example ngrok or cloudflared) and use the public URL it gives you.
  • It must accept POST with a JSON body and respond quickly with 200. Do any slowprocessing after responding.
  • It should be hard to guess, for example by including a random token in the path as in theexample above. The notification call itself is not authenticated, so an unguessable path iswhat prevents third parties from posting fake results to it.
  • It should be idempotent. You will receive several notifications for the same transaction,and you should tolerate a repeat of one you have already handled.

What you receive

The body is a Notification object:

FieldDescription
statusThe current TransactionStatus: WAITING_FOR_CARD, PIN_REQUIRED, BANK_AUTHORIZATION, or COMPLETED
ecrIdYour ECR identifier, as sent in ecrParams
ecrTransactionIdYour transaction id — use this to correlate
terminalTransactionIdThe terminal's transaction id, once assigned
resultPresent on the final notification: the full TransactionResult

Progress notification

{
  "status": "WAITING_FOR_CARD",
  "ecrId": "POS_01",
  "ecrTransactionId": "ECR-mrt1levt-eqi21j"
}

The typical sequence is WAITING_FOR_CARD → PIN_REQUIRED → BANK_AUTHORIZATION →

COMPLETED. Use these to drive a live status display for the cashier. Not every step occurs in

every transaction — a contactless payment under the floor limit may never send PIN_REQUIRED.

Final notification

The COMPLETED notification carries the outcome in result:

{
  "status": "COMPLETED",
  "ecrId": "POS_01",
  "ecrTransactionId": "ECR-mrt1levt-eqi21j",
  "terminalTransactionId": "14",
  "result": {
    "status": "OK",
    "responseCode": "000",
    "authorizationCode": "213462",
    "terminalTransactionId": "14",
    "signatureRequired": false,
    "forcedOffline": false,
    "customerReceipt": "...",
    "cashierReceipt": "..."
  }
}

Read the outcome from result.responseCode: "000" means approved, and authorizationCode

is present only in that case. Any other value is a decline code from the acquirer.

Correlating a notification to your transaction

Match on ecrTransactionId — the identifier you generated and sent on the request. It is the

only value you control and know in advance.

terminalTransactionId is assigned by the terminal and is only known after the fact, so use it

as a fallback. If a notification matches nothing you are tracking, log it and ignore it rather

than failing.

Delivery guarantees

Warning
Notifications are delivered once and are not retried, and the reachability of your
notificationUrl is not validated beforehand. If your endpoint is down, misconfigured, or slow
to respond at that moment, the result is lost — the API will not send it again.

Because of this, never treat the notification as your only source of truth. Always implement the

recovery path below.

Recovering a missed result

If you receive a 202 and no notification arrives, or a request fails with a connection error, ask

the terminal what happened:

GET /last-transaction/{terminal-id}

Then verify that

transactionResult.finalTransactionParams.ecrTransactionId matches the transaction you are

recovering.

Warning
The terminal may return the previous (one-before-last) transaction if the original request
failed very late. The ecrTransactionId check is not optional — without it you risk reconciling
against the wrong payment.

Choosing waitTime

SituationSuggestion
Attended checkout, cashier waiting at the screenKeep the default 20, and handle the 202 path
You want the result in the HTTP response more oftenRaise waitTime (maximum 300)
You prefer to return control to the POS immediatelyLower waitTime and rely on notifications

Note
Always set your client/socket timeout above waitTime, with a margin. Issuer delays can add
around 30 seconds. If your client times out first you lose a result that was about to arrive,
and you then have to recover it with last-transaction.

Common pitfalls

PitfallConsequenceFix
Treating 202 as an errorCashier sees a failure for a payment that succeedsTreat 202 as "in progress" and wait for the notification
notificationUrl not reachable from the internetNo notification ever arrivesUse a public HTTPS URL; use a tunnel in development
Client timeout lower than waitTimeConnection dropped just before the result arrivesSet the timeout above waitTime plus a margin
Relying only on notificationsOccasional lost results, since there is no retryImplement last-transaction recovery
Correlating on terminalTransactionIdCannot match the early notificationsCorrelate on ecrTransactionId
Slow notification endpointDelivery may fail; there is no second attemptRespond 200 immediately, process afterwards

Reviews